﻿#include "MusicEngine.h"
#include<qfile.h>
#include<qaudio.h>
#include<qdir.h>
#include<qmessagebox.h>
#include<qdiriterator.h>
#include<qaudiooutput.h>
#include<QtConcurrent>
#include<ctime>


MusicEngine::MusicEngine(QObject* parent)
	: QObject(parent)
	, m_playMode(PlayMode::PlayInOrder)
	, m_curPlaying(0)
	, m_player(new QMediaPlayer(this))
	, m_audioOut(new QAudioOutput(this))
	, m_songManager(PlaylistManager::getInstance())
{	
	//emit modeChanged(m_playMode);
	m_player->setAudioOutput(m_audioOut);
	//initAutoPlay();

	initAllSignal();

}

MusicEngine::~MusicEngine()
{}

qint64 MusicEngine::position() const
{
	return m_player->position();
}

void MusicEngine::setPosition(qint64 pos)
{
	m_player->setPosition(pos);
}

void MusicEngine::play()
{	
	m_player->play();
}

void MusicEngine::play(const QUrl& source)
{
	m_player->setSource(source);
	play();
}

void MusicEngine::play(int listIndex)
{
	auto curList = m_songManager.getCurSongList();
	if (listIndex > (*curList).size() - 1) {
		return;
	}
	m_player->setSource((*curList)[listIndex].url);
	m_player->play();
}

void MusicEngine::pause()
{
	m_player->pause();
}

void MusicEngine::stop()
{
	m_player->stop();
}

void MusicEngine::setPlayMode(PlayMode mode)
{
	m_playMode = mode;
	//emit modeChanged(mode);
}

MusicEngine::PlayMode MusicEngine::getCurPlayMode()
{
	return m_playMode;
}

//void MusicEngine::setLocalMuseDir(const QString& localDir)
//{
//	QDir dir(localDir);
//	if (!dir.exists())
//	{
//		QMessageBox::warning(nullptr, "文件夹", localDir + "下打开失败");
//		return;
//	}
//
//	//异步扫描
//	musicFromLocal_Async(localDir);
//
//}

void MusicEngine::setSource(const QUrl& source)
{
	m_player->setSource(source);
}

void MusicEngine::setSource(const QString& localPath)
{
	m_player->setSource(QUrl::fromLocalFile(localPath));
}

void MusicEngine::playNextMusic()
{
	auto curList = m_songManager.getCurSongList();
	if ((*curList).size() <= 0) {
		return;
	}

	switch (m_playMode)
	{

	case MusicEngine::PlayInOrder:
		if (m_curPlaying == (*curList).size() - 1)
		{
			m_curPlaying = 0;
			play((*curList)[m_curPlaying].url);
		}
		else
		{
			play((*curList)[++m_curPlaying].url);
		}
		break;

	case MusicEngine::Shuffle:
	{
		std::srand(time(nullptr));
		int count = 0;
		int newCur;
		do
		{
			newCur = std::rand() % (*curList).size();			
			++count;
		} while (newCur == m_curPlaying && count <= 3);

		m_curPlaying = newCur;
		play((*curList)[m_curPlaying].url);
		break;
	}


	case MusicEngine::RepeatSingle:

		if (m_curPlaying == (*curList).size() - 1)
		{
			m_curPlaying = 0;
			play((*curList)[m_curPlaying].url);
		}
		else
		{
			play((*curList)[++m_curPlaying].url);
		}

		break;

	default:
		break;
	}

	emit getCurIndex(m_curPlaying);
}

void MusicEngine::playPrevMusic()
{
	auto curList = m_songManager.getCurSongList();
	if (curList->size() <= 0) {
		return;
	}

	switch (m_playMode)
	{

	case MusicEngine::PlayInOrder:
		if (m_curPlaying == 0)
		{
			m_curPlaying = curList->size() - 1;
			play((*curList)[m_curPlaying].url);
		}
		else
		{
			play((*curList)[--m_curPlaying].url);
		}
		break;

	case MusicEngine::Shuffle:
	{
		std::srand(time(nullptr));
		int count = 0;
		int newCur;
		do
		{
			newCur = std::rand() % (*curList).size();			
			++count;
		} while (newCur == m_curPlaying && count <= 3);
		m_curPlaying = newCur;
		play((*curList)[m_curPlaying].url);
		break;
	}


	case MusicEngine::RepeatSingle:

		if (m_curPlaying == 0)
		{
			m_curPlaying = curList->size() - 1;
			play((*curList)[m_curPlaying].url);
		}
		else
		{
			play((*curList)[--m_curPlaying].url);
		}
		break;

	default:
		break;
	}
	getCurIndex(m_curPlaying);
}

QMediaPlayer::PlaybackState MusicEngine::playbackState() const
{
	return m_player->playbackState();
}

QMediaMetaData MusicEngine::metaData() const
{
	return m_player->metaData();
}

int MusicEngine::curDuration()
{
	QMediaMetaData data = m_player->metaData();
	return data.value(data.Duration).toInt();
}

QUrl MusicEngine::source()
{
	return m_player->source();
}

void MusicEngine::setCurIndex(unsigned int index)
{
	m_curPlaying = index;
}



//void MusicEngine::musicFromLocal_Async(const QString& dirPath, int batchSize)
//{
//	QtConcurrent::run(
//		[=]()
//		{
//		QStringList filter{ "*.mp3","*.wav","*.flac","*.ogg" };
//
//		QDirIterator it(dirPath, filter, QDir::Files, QDirIterator::Subdirectories);
//		QStringList batch;
//		while (it.hasNext())
//		{
//			//返回文件路径
//			batch << it.next();
//			if (batch.size() >= batchSize) {
//				emit songsScannedBatch(batch);
//				batch.clear();
//			}
//		}
//
//		if ( !batch.empty() )
//		{
//			emit songsScannedBatch(batch);
//		}
//			
//		emit scanFinished();
//	});
//}

void MusicEngine::initAutoPlay()
{

	connect(m_player, &QMediaPlayer::mediaStatusChanged,
		[this](QMediaPlayer::MediaStatus status) {
			//const QList<Song>& localList(m_songList.getLocalList());
			auto curList = m_songManager.getCurSongList();
			//播放到末尾
			if (status == QMediaPlayer::EndOfMedia
				&& curList->size() > 0) {
				
				//const QList<Song>& onlineList(m_songList.getOnlineList());

				switch (m_playMode)
				{

				case MusicEngine::PlayInOrder:
					if (m_curPlaying == curList->size() - 1)
					{
						m_curPlaying = 0;
						play((*curList)[m_curPlaying].url);
					}
					else
					{
						play((*curList)[++m_curPlaying].url);
					}
					break;

				case MusicEngine::Shuffle:
				{
					std::srand(time(nullptr));
					int count = 0;
					int newCur;
					do
					{
						newCur = std::rand() % (*curList).size();						
						++count;
					} while (newCur == m_curPlaying && count <= 3);
					m_curPlaying = newCur;
					play((*curList)[m_curPlaying].url);
					break;
				}


				case MusicEngine::RepeatSingle:
					play();
					break;

				default:
					break;
				}
				//getCurIndex(m_curPlaying);
				emit getCurIndex(m_curPlaying);
			}
		});
}

void MusicEngine::initAllSignal()
{
	connect(m_player, &QMediaPlayer::mediaStatusChanged
		, this, &MusicEngine::mediaStatusChanged);

	connect(m_player, &QMediaPlayer::playbackStateChanged
		, this, &MusicEngine::playbackStateChanged);

	connect(m_player, &QMediaPlayer::errorOccurred
		, this, &MusicEngine::errorOccurred);


	connect(&m_songManager, &PlaylistManager::scanFinished, this,
		[this]() {
			auto curList = m_songManager.getCurSongList();
			if ((*curList).size() >= 0)
			{
				m_player->setSource(
					(*curList)[0].url);
				emit getCurIndex(0);
			}
		}
	, Qt::SingleShotConnection);

	connect(m_player, &QMediaPlayer::positionChanged, this,
		[this](qint64 pos) {
			emit positionChanged(pos);
		});

	connect(m_player, &QMediaPlayer::sourceChanged, this, 
		[this](const QUrl& media) {
			emit sourceChanged(media);
		});

	connect(m_player, &QMediaPlayer::durationChanged, this,
		[this](qint64 duration) {
			emit durationChanged(duration);
		});
}

void MusicEngine::setVolume(int value) {
	if (value < 0) value = 0;
	if (value > 100) value = 100;
	m_audioOut->setVolume(value * 1.0f / 100);
}